# -*- coding: utf-8 -*-
from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List
import crud
import app.models.articles as articles
import schemas


import logging
from fastapi import FastAPI
from demo.common.logging.logging_config import setup_logging
setup_logging()
logger = logging.getLogger(__name__)

# log_format = "%(asctime)s - %(levelname)s - Process ID: %(process)d, Thread ID: %(thread)d, Thread Name: %(threadName)s - %(message)s"
# logging.basicConfig(
#     level=logging.INFO,
#     format=log_format,
#     handlers=[
#         logging.FileHandler("/tmp/fast-demo.log"),
#         logging.StreamHandler()
#     ]
# )

# logging.getLogger('main.app').setLevel(logging.INFO)

# 初始化数据库
# from database import engine
# articles.Base.metadata.create_all(bind=engine)
from fastapi import FastAPI, Request

# https://dev.to/uponthesky/python-post-reviewhow-to-implement-a-transactional-decorator-in-fastapi-sqlalchemy-ein 这个好像也是一个，但没有细看
# https://docs.sqlalchemy.org/en/20/orm/contextual.html 这篇有空可以看下
# https://fastapi.tiangolo.com/tutorial/middleware/ 这个可以
# https://fastapi.tiangolo.com/advanced/middleware/ 一些例子
# 可以点击这个进去看
from fastapi.middleware.trustedhost import TrustedHostMiddleware

# 这个方法不能实现，因为 DBSessionMiddleware 的线程和执行的线程是不一样的
# 2024-05-08 15:31:26,893 - main - INFO PID(57002)-TID(139819065488448) - create session <sqlalchemy.orm.session.Session object at 0x7f2a26bebe20>
# 2024-05-08 15:31:26,894 - main - INFO PID(57002)-TID(139819005687360) - yield db <sqlalchemy.orm.session.Session object at 0x7f2a26be9480>
class DBSessionMiddleware:
    def __init__(self, app: FastAPI):
        self.app = app

    async def __call__(self, scope, receive, send):
        session = ScopedSession()
        logger.info(f"create session {session}")
        try:
            response = await self.app(scope, receive, send)
        finally:
            logger.info(f"release session {session}")
            session.close()
            ScopedSession.remove()
        return response



app = FastAPI()
# app.add_middleware(DBSessionMiddleware)

# 使用这个 middleware 实现 ScopedSession 的创建和释放
@app.middleware("http")
async def add_process_remove_scoped_session(request: Request, call_next):
    session = ScopedSession()
    logger.info(f"create session {session}")
    try:
        response = await call_next(request)
    finally:
        session.close()
        ScopedSession.remove()
    return response

from database import SessionFactory
from database import ScopedSession
# Dependency
def get_db():
    db = ScopedSession()
    # db = SessionLocal()
    try:
        logger.info(f"yield db {db}")
        yield db
    finally:
        logger.info(f"Closing db")
        # db.close()
        # db.expunge_all()
        # ScopedSession.remove()
        # 这个方法可以多次调用没有问题
        # ScopedSession.remove()

@app.get("/")
async def read_root():
    logger.info("read_root go ==============")
    return {"Hello": "World"}

@app.get("/hello/{name}")
async def read_name(name: str):
    return {"message": f"Hello, {name}!"}
    
@app.post("/articles/", response_model=schemas.Article)
def create_article(article: schemas.ArticleCreate, db: Session = Depends(get_db)):
    logger.info("create_article")
    return crud.create_article(db=db, article=article)

@app.get("/articles/", response_model=List[schemas.Article])
def read_articles(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    articles = crud.get_articles(db, skip=skip, limit=limit)
    return articles

@app.get("/articles/{article_id}", response_model=schemas.Article)
def read_article(article_id: int, db: Session = Depends(get_db)):
    db_article = crud.get_article(db, article_id=article_id)
    if db_article is None:
        raise HTTPException(status_code=404, detail="Article not found")
    return db_article

@app.put("/articles/{article_id}", response_model=schemas.Article)
def update_article(article_id: int, article: schemas.ArticleUpdate, db: Session = Depends(get_db)):
    return crud.update_article(db=db, article_id=article_id, article=article)

@app.delete("/articles/{article_id}", response_model=schemas.Article)
def delete_article(article_id: int, db: Session = Depends(get_db)):
    return crud.delete_article(db=db, article_id=article_id)

# if __name__ == "__main__":
#     import uvicorn
#     uvicorn.run(
#             app=app,
#         )